using System.Net;
using Aliyun.OSS;
using Microsoft.Extensions.Options;
using Vin.Extension.Framework.Upload.Aliyun.Options;
using Vin.Extension.Framework.Upload.Options;
using Vin.Tool.AspNetCore.Service;
using Vin.Tool.Core.PathCategory;
using Vin.Tool.Domain.ExceptionModel;

namespace Vin.Extension.Framework.Upload.Aliyun.Service;

public class AliyunOssService : VinBaseService
{
    private readonly IOptionsMonitor<OssOption> _ossOption;
    private readonly IOptionsMonitor<UploadOption> _uploadOption;

    private OssClient _ossClient;

    public AliyunOssService(IOptionsMonitor<OssOption> ossOption, IOptionsMonitor<UploadOption> uploadOption)
    {
        _ossOption = ossOption;
        _uploadOption = uploadOption;
        var option = _ossOption.CurrentValue;
        if (!option.IsValidate)
        {
            throw new BusinessException("请检查阿里云OSS配置是否正确");
        }

        _ossClient = new OssClient(option.Endpoint, option.AccessKeyId, option.AccessKeySecret);
    }

    public string Upload(string dir, string extension, Stream data)
    {
        return Upload(GenerateDirPath(dir, extension), data);
    }
    
    public string Upload(string dir, string extension, byte[] data)
    {
        return Upload(GenerateDirPath(dir, extension), new MemoryStream(data));
    }


    // ---------------- 以下为私有方法 ----------------

    /// <summary>
    /// 上传文件（Stream）
    /// </summary>
    private string Upload(string path, Stream data)
    {
        try
        {
            // 发起上传
            var result = _ossClient.PutObject(_ossOption.CurrentValue.Bucket, path, data);
            if (result.HttpStatusCode == HttpStatusCode.OK)
            {
                return Path.Join(_uploadOption.CurrentValue.Host, "/" + path);
            }
        }
        catch (Exception e)
        {
            throw new BusinessException(e.Message);
        }

        throw new BusinessException("上传失败");
    }
    
    /// <summary>
    /// 生成文件路径
    /// </summary>
    private string GenerateDirPath(string dir, string extension)
    {
        dir = PathTool.DirPathCheck(dir, false);
        extension = PathTool.ExtensionCheck(extension);
        return Path.Join(dir, Guid.NewGuid().ToString("N") + extension);
    }
}